﻿// Decompiled with JetBrains decompiler
// Type: TaleWorlds.MountAndBlade.MissionMultiplayerFlagDomination
// Assembly: TaleWorlds.MountAndBlade, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
// MVID: D5209D1B-76B5-47CA-B957-255CD4B2CE6B
// Assembly location: D:\steam\steamapps\common\Mount & Blade II Bannerlord\bin\Win64_Shipping_Client\TaleWorlds.MountAndBlade.dll

using NetworkMessages.FromClient;
using NetworkMessages.FromServer;
using System;
using System.Collections.Generic;
using System.Linq;
using TaleWorlds.Core;
using TaleWorlds.Engine;
using TaleWorlds.Library;
using TaleWorlds.MountAndBlade.MissionRepresentatives;
using TaleWorlds.MountAndBlade.Network.Messages;
using TaleWorlds.MountAndBlade.Objects;
using TaleWorlds.ObjectSystem;

#nullable disable
namespace TaleWorlds.MountAndBlade
{
  public class MissionMultiplayerFlagDomination : 
    MissionMultiplayerGameModeBase,
    IAnalyticsFlagInfo,
    IMissionBehavior
  {
    public const int NumberOfFlagsInGame = 3;
    public const float MoraleRoundPrecision = 0.01f;
    public const int DefaultGoldAmountForTroopSelectionForSkirmish = 300;
    public const int MaxGoldAmountToCarryOverForSkirmish = 80;
    private const int MaxGoldAmountToCarryOverForSurvivalForSkirmish = 30;
    public const int InitialGoldAmountForTroopSelectionForBattle = 200;
    public const int DefaultGoldAmountForTroopSelectionForBattle = 120;
    public const int MaxGoldAmountToCarryOverForBattle = 110;
    private const int MaxGoldAmountToCarryOverForSurvivalForBattle = 20;
    private const float MoraleGainOnTick = 0.000625f;
    private const float MoralePenaltyPercentageIfNoPointsCaptured = 0.1f;
    private const float MoraleTickTimeInSeconds = 0.25f;
    public const float TimeTillFlagRemovalForPriorInfoInSeconds = 30f;
    public const float PointRemovalTimeInSecondsForBattle = 210f;
    public const float PointRemovalTimeInSecondsForCaptain = 180f;
    public const float PointRemovalTimeInSecondsForSkirmish = 120f;
    public const float MoraleMultiplierForEachFlagForBattle = 0.75f;
    public const float MoraleMultiplierForEachFlagForCaptain = 1f;
    private const float MoraleMultiplierOnLastFlagForBattle = 3.5f;
    private static int _defaultGoldAmountForTroopSelection = -1;
    private static int _maxGoldAmountToCarryOver = -1;
    private static int _maxGoldAmountToCarryOverForSurvival = -1;
    private const float MoraleMultiplierOnLastFlagForCaptainSkirmish = 2f;
    public const float MoraleMultiplierForEachFlagForSkirmish = 2f;
    private readonly float _pointRemovalTimeInSeconds = -1f;
    private readonly float _moraleMultiplierForEachFlag = -1f;
    private readonly float _moraleMultiplierOnLastFlag = -1f;
    private Team[] _capturePointOwners;
    private bool _flagRemovalOccured;
    private float _nextTimeToCheckForPointRemoval = float.MinValue;
    private MissionMultiplayerGameModeFlagDominationClient _gameModeFlagDominationClient;
    private float _morale;
    private readonly MultiplayerGameType _gameType;
    private int[] _agentCountsOnSide = new int[2];
    private (int, int)[] _defenderAttackerCountsInFlagArea = new (int, int)[3];

    public override bool IsGameModeHidingAllAgentVisuals
    {
      get
      {
        return this._gameType == MultiplayerGameType.Captain || this._gameType == MultiplayerGameType.Battle;
      }
    }

    public override bool IsGameModeUsingOpposingTeams => true;

    public MBReadOnlyList<FlagCapturePoint> AllCapturePoints { get; private set; }

    public float MoraleRounded
    {
      get => (float) (int) ((double) this._morale / 0.0099999997764825821) * 0.01f;
    }

    public bool GameModeUsesSingleSpawning
    {
      get
      {
        return this.GetMissionType() == MultiplayerGameType.Captain || this.GetMissionType() == MultiplayerGameType.Battle;
      }
    }

    public bool UseGold() => this._gameModeFlagDominationClient.IsGameModeUsingGold;

    public override bool AllowCustomPlayerBanners() => false;

    public override bool UseRoundController() => true;

    public MissionMultiplayerFlagDomination(MultiplayerGameType gameType)
    {
      this._gameType = gameType;
      switch (this._gameType)
      {
        case MultiplayerGameType.Battle:
          this._moraleMultiplierForEachFlag = 0.75f;
          this._pointRemovalTimeInSeconds = 210f;
          this._moraleMultiplierOnLastFlag = 3.5f;
          MissionMultiplayerFlagDomination._defaultGoldAmountForTroopSelection = 120;
          MissionMultiplayerFlagDomination._maxGoldAmountToCarryOver = 110;
          MissionMultiplayerFlagDomination._maxGoldAmountToCarryOverForSurvival = 20;
          break;
        case MultiplayerGameType.Captain:
          this._moraleMultiplierForEachFlag = 1f;
          this._pointRemovalTimeInSeconds = 180f;
          this._moraleMultiplierOnLastFlag = 2f;
          break;
        case MultiplayerGameType.Skirmish:
          this._moraleMultiplierForEachFlag = 2f;
          this._pointRemovalTimeInSeconds = 120f;
          this._moraleMultiplierOnLastFlag = 2f;
          MissionMultiplayerFlagDomination._defaultGoldAmountForTroopSelection = 300;
          MissionMultiplayerFlagDomination._maxGoldAmountToCarryOver = 80;
          MissionMultiplayerFlagDomination._maxGoldAmountToCarryOverForSurvival = 30;
          break;
      }
    }

    public override MultiplayerGameType GetMissionType() => this._gameType;

    public override void OnBehaviorInitialize()
    {
      base.OnBehaviorInitialize();
      this._gameModeFlagDominationClient = Mission.Current.GetMissionBehavior<MissionMultiplayerGameModeFlagDominationClient>();
      this._morale = 0.0f;
      this._capturePointOwners = new Team[3];
      this.AllCapturePoints = (MBReadOnlyList<FlagCapturePoint>) Mission.Current.MissionObjects.FindAllWithType<FlagCapturePoint>().ToMBList<FlagCapturePoint>();
      foreach (FlagCapturePoint allCapturePoint in (List<FlagCapturePoint>) this.AllCapturePoints)
      {
        allCapturePoint.SetTeamColorsWithAllSynched(4284111450U, uint.MaxValue);
        this._capturePointOwners[allCapturePoint.FlagIndex] = (Team) null;
      }
    }

    public override void AfterStart()
    {
      base.AfterStart();
      this.RoundController.OnRoundStarted += new Action(this.OnPreparationStart);
      MissionPeer.OnPreTeamChanged += new MissionPeer.OnTeamChangedDelegate(this.OnPreTeamChanged);
      this.RoundController.OnPreparationEnded += new Action(this.OnPreparationEnded);
      if (this.WarmupComponent != null)
        this.WarmupComponent.OnWarmupEnding += new Action(this.OnWarmupEnding);
      this.RoundController.OnPreRoundEnding += new Action(this.OnRoundEnd);
      this.RoundController.OnPostRoundEnded += new Action(this.OnPostRoundEnd);
      BasicCultureObject firstObject1 = MBObjectManager.Instance.GetObject<BasicCultureObject>(MultiplayerOptions.OptionType.CultureTeam1.GetStrValue());
      BasicCultureObject firstObject2 = MBObjectManager.Instance.GetObject<BasicCultureObject>(MultiplayerOptions.OptionType.CultureTeam2.GetStrValue());
      if (firstObject1 == null)
        firstObject1 = MBObjectManager.Instance.GetFirstObject<BasicCultureObject>();
      if (firstObject2 == null)
        firstObject2 = MBObjectManager.Instance.GetFirstObject<BasicCultureObject>();
      Banner banner1 = new Banner(firstObject1.BannerKey, firstObject1.BackgroundColor1, firstObject1.ForegroundColor1);
      Banner banner2 = new Banner(firstObject2.BannerKey, firstObject2.BackgroundColor2, firstObject2.ForegroundColor2);
      this.Mission.Teams.Add(BattleSideEnum.Attacker, firstObject1.BackgroundColor1, firstObject1.ForegroundColor1, banner1, false, true);
      this.Mission.Teams.Add(BattleSideEnum.Defender, firstObject2.BackgroundColor2, firstObject2.ForegroundColor2, banner2, false, true);
    }

    protected override void AddRemoveMessageHandlers(
      GameNetwork.NetworkMessageHandlerRegistererContainer registerer)
    {
      registerer.RegisterBaseHandler<RequestForfeitSpawn>(new GameNetworkMessage.ClientMessageHandlerDelegate<GameNetworkMessage>(this.HandleClientEventRequestForfeitSpawn));
    }

    public override void OnRemoveBehavior()
    {
      this.RoundController.OnRoundStarted -= new Action(this.OnPreparationStart);
      MissionPeer.OnPreTeamChanged -= new MissionPeer.OnTeamChangedDelegate(this.OnPreTeamChanged);
      this.RoundController.OnPreparationEnded -= new Action(this.OnPreparationEnded);
      if (this.WarmupComponent != null)
        this.WarmupComponent.OnWarmupEnding -= new Action(this.OnWarmupEnding);
      this.RoundController.OnPreRoundEnding -= new Action(this.OnRoundEnd);
      this.RoundController.OnPostRoundEnded -= new Action(this.OnPostRoundEnd);
      base.OnRemoveBehavior();
    }

    public override void OnPeerChangedTeam(NetworkCommunicator peer, Team oldTeam, Team newTeam)
    {
      if (oldTeam == null || oldTeam == newTeam || !this.UseGold() || this.WarmupComponent != null && this.WarmupComponent.IsInWarmup)
        return;
      this.ChangeCurrentGoldForPeer(peer.GetComponent<MissionPeer>(), 0);
    }

    private void OnPreparationStart() => this.NotificationsComponent.PreparationStarted();

    public override void OnMissionTick(float dt)
    {
      base.OnMissionTick(dt);
      if (this.MissionLobbyComponent.CurrentMultiplayerState != MissionLobbyComponent.MultiplayerGameState.Playing)
        return;
      if (MultiplayerOptions.OptionType.NumberOfBotsPerFormation.GetIntValue() > 0)
      {
        this.CheckForPlayersSpawningAsBots();
        this.CheckPlayerBeingDetached();
      }
      if (!this.RoundController.IsRoundInProgress || !this.CanGameModeSystemsTickThisFrame)
        return;
      if (!this._flagRemovalOccured)
        this.CheckRemovingOfPoints();
      this.CheckMorales();
      this.TickFlags();
    }

    private void CheckForPlayersSpawningAsBots()
    {
      foreach (NetworkCommunicator networkPeer in GameNetwork.NetworkPeers)
      {
        if (networkPeer.IsSynchronized)
        {
          MissionPeer component = networkPeer.GetComponent<MissionPeer>();
          if (component != null && component.ControlledAgent == null && component.Team != null && component.ControlledFormation != null && component.SpawnCountThisRound > 0)
          {
            if (!component.HasSpawnTimerExpired && component.SpawnTimer.Check(this.Mission.CurrentTime))
              component.HasSpawnTimerExpired = true;
            if (component.HasSpawnTimerExpired && component.WantsToSpawnAsBot && component.ControlledFormation.HasUnitsWithCondition((Func<Agent, bool>) (agent => agent.IsActive() && agent.IsAIControlled)))
            {
              Agent newAgent = (Agent) null;
              Agent followingAgent = component.FollowedAgent;
              if (followingAgent != null && followingAgent.IsActive() && followingAgent.IsAIControlled && component.ControlledFormation.HasUnitsWithCondition((Func<Agent, bool>) (agent => agent == followingAgent)))
              {
                newAgent = followingAgent;
              }
              else
              {
                float maxHealth = 0.0f;
                component.ControlledFormation.ApplyActionOnEachUnit((Action<Agent>) (agent =>
                {
                  if ((double) agent.Health <= (double) maxHealth)
                    return;
                  maxHealth = agent.Health;
                  newAgent = agent;
                }));
              }
              Mission.Current.ReplaceBotWithPlayer(newAgent, component);
              component.WantsToSpawnAsBot = false;
              component.HasSpawnTimerExpired = false;
            }
          }
        }
      }
    }

    private bool GetMoraleGain(out float moraleGain)
    {
      List<FlagCapturePoint> list = this.AllCapturePoints.Where<FlagCapturePoint>((Func<FlagCapturePoint, bool>) (flag => !flag.IsDeactivated && this.GetFlagOwnerTeam(flag) != null && flag.IsFullyRaised)).ToList<FlagCapturePoint>();
      int f = list.Count<FlagCapturePoint>((Func<FlagCapturePoint, bool>) (flag => this.GetFlagOwnerTeam(flag).Side == BattleSideEnum.Attacker)) - list.Count<FlagCapturePoint>((Func<FlagCapturePoint, bool>) (flag => this.GetFlagOwnerTeam(flag).Side == BattleSideEnum.Defender));
      int num1 = MathF.Sign(f);
      moraleGain = 0.0f;
      if (num1 == 0)
        return false;
      float num2 = 0.000625f * this._moraleMultiplierForEachFlag * (float) MathF.Abs(f);
      moraleGain = num1 <= 0 ? MBMath.ClampFloat((float) num1 - this._morale, -2f, -1f) * num2 : MBMath.ClampFloat((float) num1 - this._morale, 1f, 2f) * num2;
      if (this._flagRemovalOccured)
        moraleGain *= this._moraleMultiplierOnLastFlag;
      return true;
    }

    public float GetTimeUntilBattleSideVictory(BattleSideEnum side)
    {
      float a = float.MaxValue;
      if (side == BattleSideEnum.Attacker && (double) this._morale > 0.0 || side == BattleSideEnum.Defender && (double) this._morale < 0.0)
        a = this.RoundController.RemainingRoundTime;
      float b = float.MaxValue;
      float moraleGain;
      this.GetMoraleGain(out moraleGain);
      if (side == BattleSideEnum.Attacker && (double) moraleGain > 0.0)
        b = (1f - this._morale) / moraleGain;
      else if (side == BattleSideEnum.Defender && (double) moraleGain < 0.0)
        b = (float) ((-1.0 - (double) this._morale) / ((double) moraleGain / 0.25));
      return MathF.Min(a, b);
    }

    private void CheckMorales()
    {
      float moraleGain;
      if (!this.GetMoraleGain(out moraleGain))
        return;
      this._morale += moraleGain;
      this._morale = MBMath.ClampFloat(this._morale, -1f, 1f);
      GameNetwork.BeginBroadcastModuleEvent();
      GameNetwork.WriteMessage((GameNetworkMessage) new FlagDominationMoraleChangeMessage(this.MoraleRounded));
      GameNetwork.EndBroadcastModuleEvent(GameNetwork.EventBroadcastFlags.None);
      this._gameModeFlagDominationClient?.OnMoraleChanged(this.MoraleRounded);
      MPPerkObject.RaiseEventForAllPeers(MPPerkCondition.PerkEventFlags.MoraleChange);
    }

    private void CheckRemovingOfPoints()
    {
      if ((double) this._nextTimeToCheckForPointRemoval < 0.0)
        this._nextTimeToCheckForPointRemoval = this.Mission.CurrentTime + this._pointRemovalTimeInSeconds;
      if ((double) this.Mission.CurrentTime < (double) this._nextTimeToCheckForPointRemoval)
        return;
      this._nextTimeToCheckForPointRemoval += this._pointRemovalTimeInSeconds;
      List<BattleSideEnum> battleSideEnumList = new List<BattleSideEnum>();
      foreach (Team team1 in (List<Team>) this.Mission.Teams)
      {
        Team team = team1;
        if (team.Side != BattleSideEnum.None)
        {
          int num = (int) team.Side * 2 - 1;
          if (this.AllCapturePoints.All<FlagCapturePoint>((Func<FlagCapturePoint, bool>) (cp => this.GetFlagOwnerTeam(cp) != team)))
          {
            if (this.AllCapturePoints.FirstOrDefault<FlagCapturePoint>((Func<FlagCapturePoint, bool>) (cp => this.GetFlagOwnerTeam(cp) == null)) != null)
            {
              this._morale -= 0.1f * (float) num;
              battleSideEnumList.Add(BattleSideEnum.None);
            }
            else
            {
              this._morale -= (float) (0.10000000149011612 * (double) num * 2.0);
              battleSideEnumList.Add(team.Side.GetOppositeSide());
            }
            this._morale = MBMath.ClampFloat(this._morale, -1f, 1f);
          }
          else
            battleSideEnumList.Add(team.Side);
        }
      }
      List<int> removedCapIndexList = new List<int>();
      MBList<FlagCapturePoint> mbList1 = this.AllCapturePoints.ToMBList<FlagCapturePoint>();
      foreach (BattleSideEnum battleSideEnum in battleSideEnumList)
      {
        BattleSideEnum side = battleSideEnum;
        if (side == BattleSideEnum.None)
        {
          removedCapIndexList.Add(this.RemoveCapturePoint(mbList1.GetRandomElementWithPredicate<FlagCapturePoint>((Func<FlagCapturePoint, bool>) (cp => this.GetFlagOwnerTeam(cp) == null))));
        }
        else
        {
          List<FlagCapturePoint> list = mbList1.Where<FlagCapturePoint>((Func<FlagCapturePoint, bool>) (cp => this.GetFlagOwnerTeam(cp) != null && this.GetFlagOwnerTeam(cp).Side == side)).ToList<FlagCapturePoint>();
          MBList<FlagCapturePoint> mbList2 = list.Where<FlagCapturePoint>((Func<FlagCapturePoint, bool>) (cp => this.GetNumberOfAttackersAroundFlag(cp) == 0)).ToMBList<FlagCapturePoint>();
          if (mbList2.Count > 0)
          {
            removedCapIndexList.Add(this.RemoveCapturePoint(mbList2.GetRandomElement<FlagCapturePoint>()));
          }
          else
          {
            MBList<KeyValuePair<FlagCapturePoint, int>> mbList3 = new MBList<KeyValuePair<FlagCapturePoint, int>>();
            foreach (FlagCapturePoint flagCapturePoint in list)
            {
              if (mbList3.Count == 0)
              {
                mbList3.Add(new KeyValuePair<FlagCapturePoint, int>(flagCapturePoint, this.GetNumberOfAttackersAroundFlag(flagCapturePoint)));
              }
              else
              {
                int count = this.GetNumberOfAttackersAroundFlag(flagCapturePoint);
                if (mbList3.Any<KeyValuePair<FlagCapturePoint, int>>((Func<KeyValuePair<FlagCapturePoint, int>, bool>) (cc => cc.Value > count)))
                {
                  mbList3.Clear();
                  mbList3.Add(new KeyValuePair<FlagCapturePoint, int>(flagCapturePoint, count));
                }
                else if (mbList3.Any<KeyValuePair<FlagCapturePoint, int>>((Func<KeyValuePair<FlagCapturePoint, int>, bool>) (cc => cc.Value == count)))
                  mbList3.Add(new KeyValuePair<FlagCapturePoint, int>(flagCapturePoint, count));
              }
            }
            removedCapIndexList.Add(this.RemoveCapturePoint(mbList3.GetRandomElement<KeyValuePair<FlagCapturePoint, int>>().Key));
          }
        }
        FlagCapturePoint flagCapturePoint1 = mbList1.First<FlagCapturePoint>((Func<FlagCapturePoint, bool>) (fl => fl.FlagIndex == removedCapIndexList[removedCapIndexList.Count - 1]));
        mbList1.Remove(flagCapturePoint1);
      }
      removedCapIndexList.Sort();
      int first = removedCapIndexList[0];
      int second = removedCapIndexList[1];
      FlagCapturePoint remainingFlag = this.AllCapturePoints.First<FlagCapturePoint>((Func<FlagCapturePoint, bool>) (cp => cp.FlagIndex != first && cp.FlagIndex != second));
      this.NotificationsComponent.FlagXRemaining(remainingFlag);
      GameNetwork.BeginBroadcastModuleEvent();
      GameNetwork.WriteMessage((GameNetworkMessage) new FlagDominationMoraleChangeMessage(this.MoraleRounded));
      GameNetwork.EndBroadcastModuleEvent(GameNetwork.EventBroadcastFlags.None);
      GameNetwork.BeginBroadcastModuleEvent();
      GameNetwork.WriteMessage((GameNetworkMessage) new FlagDominationFlagsRemovedMessage());
      GameNetwork.EndBroadcastModuleEvent(GameNetwork.EventBroadcastFlags.None);
      this._flagRemovalOccured = true;
      this._gameModeFlagDominationClient?.OnNumberOfFlagsChanged();
      foreach (MissionBehavior missionBehavior in this.Mission.MissionBehaviors)
      {
        if (missionBehavior is IFlagRemoved flagRemoved)
          flagRemoved.OnFlagsRemoved(remainingFlag.FlagIndex);
      }
      MPPerkObject.RaiseEventForAllPeers(MPPerkCondition.PerkEventFlags.FlagRemoval);
    }

    private int RemoveCapturePoint(FlagCapturePoint capToRemove)
    {
      int flagIndex = capToRemove.FlagIndex;
      capToRemove.RemovePointAsServer();
      GameNetwork.BeginBroadcastModuleEvent();
      GameNetwork.WriteMessage((GameNetworkMessage) new FlagDominationCapturePointMessage(flagIndex, -1));
      GameNetwork.EndBroadcastModuleEvent(GameNetwork.EventBroadcastFlags.None);
      return flagIndex;
    }

    public override void OnClearScene()
    {
      base.OnClearScene();
      this.AllCapturePoints = (MBReadOnlyList<FlagCapturePoint>) Mission.Current.MissionObjects.FindAllWithType<FlagCapturePoint>().ToMBList<FlagCapturePoint>();
      foreach (FlagCapturePoint allCapturePoint in (List<FlagCapturePoint>) this.AllCapturePoints)
      {
        allCapturePoint.ResetPointAsServer(4284111450U, uint.MaxValue);
        this._capturePointOwners[allCapturePoint.FlagIndex] = (Team) null;
      }
      this._morale = 0.0f;
      this._nextTimeToCheckForPointRemoval = float.MinValue;
      this._flagRemovalOccured = false;
    }

    public override bool CheckIfOvertime()
    {
      if (!this._flagRemovalOccured)
        return false;
      FlagCapturePoint flagCapturePoint = this.AllCapturePoints.FirstOrDefault<FlagCapturePoint>((Func<FlagCapturePoint, bool>) (flag => !flag.IsDeactivated));
      Team flagOwnerTeam = this.GetFlagOwnerTeam(flagCapturePoint);
      if (flagOwnerTeam == null)
        return false;
      return (double) ((int) flagOwnerTeam.Side * 2 - 1) * (double) this._morale < 0.0 || this.GetNumberOfAttackersAroundFlag(flagCapturePoint) > 0;
    }

    public override bool CheckForWarmupEnd()
    {
      int[] source = new int[2];
      foreach (NetworkCommunicator networkPeer in GameNetwork.NetworkPeers)
      {
        MissionPeer component = networkPeer.GetComponent<MissionPeer>();
        if (networkPeer.IsSynchronized && component?.Team != null && component.Team.Side != BattleSideEnum.None)
          ++source[(int) component.Team.Side];
      }
      return ((IEnumerable<int>) source).Sum() >= MultiplayerOptions.OptionType.MaxNumberOfPlayers.GetIntValue();
    }

    public override bool CheckForRoundEnd()
    {
      if (this.CanGameModeSystemsTickThisFrame)
      {
        if ((double) MathF.Abs(this._morale) >= 1.0)
        {
          if (!this._flagRemovalOccured)
            return true;
          FlagCapturePoint flagCapturePoint = this.AllCapturePoints.FirstOrDefault<FlagCapturePoint>((Func<FlagCapturePoint, bool>) (flag => !flag.IsDeactivated));
          Team flagOwnerTeam = this.GetFlagOwnerTeam(flagCapturePoint);
          if (flagOwnerTeam == null)
            return true;
          BattleSideEnum battleSideEnum = (double) this._morale > 0.0 ? BattleSideEnum.Attacker : BattleSideEnum.Defender;
          return flagOwnerTeam.Side == battleSideEnum && flagCapturePoint.IsFullyRaised && this.GetNumberOfAttackersAroundFlag(flagCapturePoint) == 0;
        }
        bool flag1 = this.Mission.AttackerTeam.ActiveAgents.Count > 0;
        bool flag2 = this.Mission.DefenderTeam.ActiveAgents.Count > 0;
        if (flag1 & flag2)
          return false;
        if (!this.SpawnComponent.AreAgentsSpawning())
          return true;
        bool[] flagArray = new bool[2];
        if (this.UseGold())
        {
          foreach (NetworkCommunicator networkPeer in GameNetwork.NetworkPeers)
          {
            MissionPeer component = networkPeer.GetComponent<MissionPeer>();
            if (component?.Team != null && component.Team.Side != BattleSideEnum.None && !flagArray[(int) component.Team.Side])
            {
              string strValue = MultiplayerOptions.OptionType.CultureTeam1.GetStrValue();
              if (component.Team.Side != BattleSideEnum.Attacker)
                strValue = MultiplayerOptions.OptionType.CultureTeam2.GetStrValue();
              if (this.GetCurrentGoldForPeer(component) >= MultiplayerClassDivisions.GetMinimumTroopCost(MBObjectManager.Instance.GetObject<BasicCultureObject>(strValue)))
                flagArray[(int) component.Team.Side] = true;
            }
          }
        }
        if (!flag1 && !flagArray[1] || !flag2 && !flagArray[0])
          return true;
      }
      return false;
    }

    public override bool UseCultureSelection() => false;

    private void OnWarmupEnding() => this.NotificationsComponent.WarmupEnding();

    private void OnRoundEnd()
    {
      foreach (FlagCapturePoint allCapturePoint in (List<FlagCapturePoint>) this.AllCapturePoints)
      {
        if (!allCapturePoint.IsDeactivated)
          allCapturePoint.SetMoveNone();
      }
      RoundEndReason roundEndReason = RoundEndReason.Invalid;
      bool flag1 = (double) this.RoundController.RemainingRoundTime <= 0.0 && !this.CheckIfOvertime();
      int num1 = -1;
      for (int index = 0; index < 2; ++index)
      {
        int num2 = index * 2 - 1;
        if (flag1 && (double) num2 * (double) this._morale > 0.0 || !flag1 && (double) num2 * (double) this._morale >= 1.0)
        {
          num1 = index;
          break;
        }
      }
      CaptureTheFlagCaptureResultEnum roundResult = CaptureTheFlagCaptureResultEnum.NotCaptured;
      if (num1 >= 0)
      {
        roundResult = num1 == 0 ? CaptureTheFlagCaptureResultEnum.DefendersWin : CaptureTheFlagCaptureResultEnum.AttackersWin;
        this.RoundController.RoundWinner = num1 == 0 ? BattleSideEnum.Defender : BattleSideEnum.Attacker;
        roundEndReason = flag1 ? RoundEndReason.RoundTimeEnded : RoundEndReason.GameModeSpecificEnded;
      }
      else
      {
        bool flag2 = this.Mission.AttackerTeam.ActiveAgents.Count > 0;
        bool flag3 = this.Mission.DefenderTeam.ActiveAgents.Count > 0;
        if (flag2 & flag3)
        {
          if ((double) this._morale > 0.0)
          {
            roundResult = CaptureTheFlagCaptureResultEnum.AttackersWin;
            this.RoundController.RoundWinner = BattleSideEnum.Attacker;
          }
          else if ((double) this._morale < 0.0)
          {
            roundResult = CaptureTheFlagCaptureResultEnum.DefendersWin;
            this.RoundController.RoundWinner = BattleSideEnum.Defender;
          }
          else
          {
            roundResult = CaptureTheFlagCaptureResultEnum.Draw;
            this.RoundController.RoundWinner = BattleSideEnum.None;
          }
          roundEndReason = RoundEndReason.RoundTimeEnded;
        }
        else if (flag2)
        {
          roundResult = CaptureTheFlagCaptureResultEnum.AttackersWin;
          this.RoundController.RoundWinner = BattleSideEnum.Attacker;
          roundEndReason = RoundEndReason.SideDepleted;
        }
        else if (flag3)
        {
          roundResult = CaptureTheFlagCaptureResultEnum.DefendersWin;
          this.RoundController.RoundWinner = BattleSideEnum.Defender;
          roundEndReason = RoundEndReason.SideDepleted;
        }
        else
        {
          foreach (NetworkCommunicator networkPeer in GameNetwork.NetworkPeers)
          {
            MissionPeer component = networkPeer.GetComponent<MissionPeer>();
            if (component?.Team != null && component.Team.Side != BattleSideEnum.None)
            {
              string strValue = MultiplayerOptions.OptionType.CultureTeam1.GetStrValue();
              if (component.Team.Side != BattleSideEnum.Attacker)
                strValue = MultiplayerOptions.OptionType.CultureTeam2.GetStrValue();
              if (this.GetCurrentGoldForPeer(component) >= MultiplayerClassDivisions.GetMinimumTroopCost(MBObjectManager.Instance.GetObject<BasicCultureObject>(strValue)))
              {
                this.RoundController.RoundWinner = component.Team.Side;
                roundEndReason = RoundEndReason.SideDepleted;
                roundResult = component.Team.Side == BattleSideEnum.Attacker ? CaptureTheFlagCaptureResultEnum.AttackersWin : CaptureTheFlagCaptureResultEnum.DefendersWin;
                break;
              }
            }
          }
        }
      }
      if (roundResult == CaptureTheFlagCaptureResultEnum.NotCaptured)
        return;
      this.RoundController.RoundEndReason = roundEndReason;
      this.HandleRoundEnd(roundResult);
    }

    public override void OnAgentBuild(Agent agent, Banner banner)
    {
      agent.UpdateSyncHealthToAllClients(true);
      if (!agent.IsPlayerControlled)
        return;
      agent.MissionPeer.GetComponent<FlagDominationMissionRepresentative>().UpdateSelectedClassServer(agent);
    }

    private void HandleRoundEnd(CaptureTheFlagCaptureResultEnum roundResult)
    {
      AgentVictoryLogic missionBehavior = this.Mission.GetMissionBehavior<AgentVictoryLogic>();
      if (missionBehavior == null)
        Debug.FailedAssert("Agent victory logic should not be null after someone just won/lost!", "C:\\Develop\\MB3\\Source\\Bannerlord\\TaleWorlds.MountAndBlade\\Missions\\Multiplayer\\MissionNetworkLogics\\MultiplayerGameModeLogics\\ServerGameModeLogics\\MissionMultiplayerFlagDomination.cs", nameof (HandleRoundEnd), 780);
      else if (roundResult != CaptureTheFlagCaptureResultEnum.AttackersWin)
      {
        if (roundResult != CaptureTheFlagCaptureResultEnum.DefendersWin)
          return;
        missionBehavior.SetTimersOfVictoryReactionsOnBattleEnd(BattleSideEnum.Defender);
      }
      else
        missionBehavior.SetTimersOfVictoryReactionsOnBattleEnd(BattleSideEnum.Attacker);
    }

    private void OnPostRoundEnd()
    {
      if (!this.UseGold() || this.RoundController.IsMatchEnding)
        return;
      foreach (NetworkCommunicator networkPeer in GameNetwork.NetworkPeers)
      {
        MissionPeer component = networkPeer.GetComponent<MissionPeer>();
        if (component != null && this.RoundController.RoundCount > 0)
        {
          int forTroopSelection = MissionMultiplayerFlagDomination._defaultGoldAmountForTroopSelection;
          int num = this.GetCurrentGoldForPeer(component);
          if (num < 0)
            num = MissionMultiplayerFlagDomination._maxGoldAmountToCarryOver;
          else if (component.Team != null && component.Team.Side != BattleSideEnum.None && this.RoundController.RoundWinner == component.Team.Side && component.GetComponent<FlagDominationMissionRepresentative>().CheckIfSurvivedLastRoundAndReset())
            num += MissionMultiplayerFlagDomination._maxGoldAmountToCarryOverForSurvival;
          int newAmount = forTroopSelection + MBMath.ClampInt(num, 0, MissionMultiplayerFlagDomination._maxGoldAmountToCarryOver);
          if (newAmount > MissionMultiplayerFlagDomination._defaultGoldAmountForTroopSelection)
            this.NotificationsComponent.GoldCarriedFromPreviousRound(newAmount - MissionMultiplayerFlagDomination._defaultGoldAmountForTroopSelection, component.GetNetworkPeer());
          this.ChangeCurrentGoldForPeer(component, newAmount);
        }
      }
    }

    protected override void HandleEarlyPlayerDisconnect(NetworkCommunicator networkPeer)
    {
      if (!this.RoundController.IsRoundInProgress || MultiplayerOptions.OptionType.NumberOfBotsPerFormation.GetIntValue() <= 0)
        return;
      this.MakePlayerFormationCharge(networkPeer);
    }

    private void OnPreTeamChanged(NetworkCommunicator peer, Team currentTeam, Team newTeam)
    {
      if (!peer.IsSynchronized || peer.GetComponent<MissionPeer>().ControlledAgent == null)
        return;
      this.MakePlayerFormationCharge(peer);
    }

    private void OnPreparationEnded()
    {
      if (!this.UseGold())
        return;
      List<MissionPeer>[] missionPeerListArray = new List<MissionPeer>[2];
      for (int index = 0; index < missionPeerListArray.Length; ++index)
        missionPeerListArray[index] = new List<MissionPeer>();
      foreach (NetworkCommunicator networkPeer in GameNetwork.NetworkPeers)
      {
        MissionPeer component = networkPeer.GetComponent<MissionPeer>();
        if (component != null && component.Team != null && component.Team.Side != BattleSideEnum.None)
          missionPeerListArray[(int) component.Team.Side].Add(component);
      }
      int f = missionPeerListArray[1].Count - missionPeerListArray[0].Count;
      BattleSideEnum index1 = f == 0 ? BattleSideEnum.None : (f < 0 ? BattleSideEnum.Attacker : BattleSideEnum.Defender);
      if (index1 == BattleSideEnum.None)
        return;
      int num1 = MathF.Abs(f);
      int count = missionPeerListArray[(int) index1].Count;
      if (count <= 0)
        return;
      int num2 = MissionMultiplayerFlagDomination._defaultGoldAmountForTroopSelection * num1 / 10 / count * 10;
      foreach (MissionPeer peer in missionPeerListArray[(int) index1])
        this.ChangeCurrentGoldForPeer(peer, this.GetCurrentGoldForPeer(peer) + num2);
    }

    private void CheckPlayerBeingDetached()
    {
      foreach (NetworkCommunicator networkPeer in GameNetwork.NetworkPeers)
      {
        if (networkPeer.IsSynchronized)
        {
          MissionPeer component = networkPeer.GetComponent<MissionPeer>();
          if (this.PlayerDistanceToFormation(component) >= component.CaptainBeingDetachedThreshold)
            this.MakePlayerFormationFollowPlayer(component.GetNetworkPeer());
        }
      }
    }

    private int PlayerDistanceToFormation(MissionPeer missionPeer)
    {
      float formation = 0.0f;
      if (missionPeer != null && missionPeer.ControlledAgent != null && missionPeer.ControlledFormation != null)
      {
        Vec2 vec2 = missionPeer.ControlledFormation.GetAveragePositionOfUnits(true, true);
        float num1 = vec2.Distance(missionPeer.ControlledAgent.Position.AsVec2);
        vec2 = missionPeer.ControlledFormation.OrderPosition;
        float num2 = vec2.Distance(missionPeer.ControlledAgent.Position.AsVec2);
        formation += num1 + num2;
        if (missionPeer.ControlledFormation.PhysicalClass.IsMounted())
          formation *= 0.8f;
      }
      return (int) formation;
    }

    private void MakePlayerFormationFollowPlayer(NetworkCommunicator peer)
    {
      if (!peer.IsSynchronized)
        return;
      MissionPeer component = peer.GetComponent<MissionPeer>();
      if (component.ControlledFormation == null)
        return;
      component.ControlledFormation.SetMovementOrder(MovementOrder.MovementOrderFollow(component.ControlledAgent));
      this.NotificationsComponent.FormationAutoFollowEnforced(peer);
    }

    private void MakePlayerFormationCharge(NetworkCommunicator peer)
    {
      if (!peer.IsSynchronized)
        return;
      MissionPeer component = peer.GetComponent<MissionPeer>();
      if (component.ControlledFormation == null)
        return;
      component.ControlledFormation.SetMovementOrder(MovementOrder.MovementOrderCharge);
    }

    protected override void HandleEarlyNewClientAfterLoadingFinished(NetworkCommunicator networkPeer)
    {
      networkPeer.AddComponent<FlagDominationMissionRepresentative>();
    }

    protected override void HandleNewClientAfterSynchronized(NetworkCommunicator networkPeer)
    {
      if (this.UseGold())
      {
        int num1 = this._gameType == MultiplayerGameType.Battle ? 200 : MissionMultiplayerFlagDomination._defaultGoldAmountForTroopSelection;
        int num2 = !this.RoundController.IsRoundInProgress ? num1 : 0;
        this.ChangeCurrentGoldForPeer(networkPeer.GetComponent<MissionPeer>(), num2);
        this._gameModeFlagDominationClient?.OnGoldAmountChangedForRepresentative((MissionRepresentativeBase) networkPeer.GetComponent<FlagDominationMissionRepresentative>(), num2);
      }
      if (this.AllCapturePoints == null || networkPeer.IsServerPeer)
        return;
      foreach (FlagCapturePoint flagCapturePoint in this.AllCapturePoints.Where<FlagCapturePoint>((Func<FlagCapturePoint, bool>) (cp => !cp.IsDeactivated)))
      {
        GameNetwork.BeginModuleEventAsServer(networkPeer);
        int flagIndex = flagCapturePoint.FlagIndex;
        Team capturePointOwner = this._capturePointOwners[flagCapturePoint.FlagIndex];
        int ownerTeamIndex = capturePointOwner != null ? capturePointOwner.TeamIndex : -1;
        GameNetwork.WriteMessage((GameNetworkMessage) new FlagDominationCapturePointMessage(flagIndex, ownerTeamIndex));
        GameNetwork.EndModuleEventAsServer();
      }
    }

    private bool HandleClientEventRequestForfeitSpawn(
      NetworkCommunicator peer,
      GameNetworkMessage baseMessage)
    {
      this.ForfeitSpawning(peer);
      return true;
    }

    public void ForfeitSpawning(NetworkCommunicator peer)
    {
      MissionPeer component = peer.GetComponent<MissionPeer>();
      if (component == null || !component.HasSpawnedAgentVisuals || !this.UseGold() || !this.RoundController.IsRoundInProgress)
        return;
      Mission.Current.GetMissionBehavior<MultiplayerMissionAgentVisualSpawnComponent>().RemoveAgentVisuals(component, true);
      if (GameNetwork.IsServerOrRecorder)
      {
        GameNetwork.BeginBroadcastModuleEvent();
        GameNetwork.WriteMessage((GameNetworkMessage) new RemoveAgentVisualsForPeer(component.GetNetworkPeer()));
        GameNetwork.EndBroadcastModuleEvent(GameNetwork.EventBroadcastFlags.None);
      }
      component.HasSpawnedAgentVisuals = false;
      this.ChangeCurrentGoldForPeer(component, -1);
    }

    public static void SetWinnerTeam(int winnerTeamNo)
    {
      Mission current = Mission.Current;
      MissionMultiplayerFlagDomination missionBehavior = current.GetMissionBehavior<MissionMultiplayerFlagDomination>();
      if (missionBehavior == null)
        return;
      foreach (NetworkCommunicator networkPeer in GameNetwork.NetworkPeers)
      {
        MissionPeer component = networkPeer.GetComponent<MissionPeer>();
        missionBehavior.ChangeCurrentGoldForPeer(component, 0);
      }
      for (int index = current.Agents.Count - 1; index >= 0; --index)
      {
        Agent agent = current.Agents[index];
        if (agent.IsHuman && agent.Team.MBTeam.Index != winnerTeamNo + 1)
          Mission.Current.KillAgentCheat(agent);
      }
    }

    private void TickFlags()
    {
      foreach (FlagCapturePoint allCapturePoint in (List<FlagCapturePoint>) this.AllCapturePoints)
      {
        if (!allCapturePoint.IsDeactivated)
        {
          for (int index = 0; index < 2; ++index)
            this._agentCountsOnSide[index] = 0;
          Team capturePointOwner = this._capturePointOwners[allCapturePoint.FlagIndex];
          Agent agent = (Agent) null;
          float num1 = 16f;
          AgentProximityMap.ProximityMapSearchStruct searchStruct = AgentProximityMap.BeginSearch(Mission.Current, allCapturePoint.Position.AsVec2, 6f);
          while (searchStruct.LastFoundAgent != null)
          {
            Agent lastFoundAgent = searchStruct.LastFoundAgent;
            if (lastFoundAgent.IsHuman && lastFoundAgent.IsActive())
            {
              ++this._agentCountsOnSide[(int) lastFoundAgent.Team.Side];
              float num2 = lastFoundAgent.Position.DistanceSquared(allCapturePoint.Position);
              if ((double) num2 <= (double) num1)
              {
                agent = lastFoundAgent;
                num1 = num2;
              }
            }
            AgentProximityMap.FindNext(Mission.Current, ref searchStruct);
          }
          (int, int) tuple = ValueTuple.Create<int, int>(this._agentCountsOnSide[0], this._agentCountsOnSide[1]);
          bool flag = tuple.Item1 != this._defenderAttackerCountsInFlagArea[allCapturePoint.FlagIndex].Item1 || tuple.Item2 != this._defenderAttackerCountsInFlagArea[allCapturePoint.FlagIndex].Item2;
          this._defenderAttackerCountsInFlagArea[allCapturePoint.FlagIndex] = tuple;
          bool isContested = allCapturePoint.IsContested;
          float speedMultiplier = 1f;
          if (agent != null)
          {
            BattleSideEnum side = agent.Team.Side;
            BattleSideEnum oppositeSide = side.GetOppositeSide();
            if (this._agentCountsOnSide[(int) oppositeSide] != 0)
            {
              int val1 = Math.Min(this._agentCountsOnSide[(int) side], 200);
              int val2 = Math.Min(this._agentCountsOnSide[(int) oppositeSide], 200);
              speedMultiplier = Math.Min(1f, (float) (((double) MathF.Log10((float) val1) + 1.0) / (2.0 * ((double) MathF.Log10((float) val2) + 1.0)) - 0.090000003576278687));
            }
          }
          if (capturePointOwner == null)
          {
            if (!isContested && agent != null)
              allCapturePoint.SetMoveFlag(CaptureTheFlagFlagDirection.Down, speedMultiplier);
            else if (agent == null & isContested)
              allCapturePoint.SetMoveFlag(CaptureTheFlagFlagDirection.Up, speedMultiplier);
            else if (flag)
              allCapturePoint.ChangeMovementSpeed(speedMultiplier);
          }
          else if (agent != null)
          {
            if (agent.Team != capturePointOwner && !isContested)
              allCapturePoint.SetMoveFlag(CaptureTheFlagFlagDirection.Down, speedMultiplier);
            else if (agent.Team == capturePointOwner & isContested)
              allCapturePoint.SetMoveFlag(CaptureTheFlagFlagDirection.Up, speedMultiplier);
            else if (flag)
              allCapturePoint.ChangeMovementSpeed(speedMultiplier);
          }
          else if (isContested)
            allCapturePoint.SetMoveFlag(CaptureTheFlagFlagDirection.Up, speedMultiplier);
          else if (flag)
            allCapturePoint.ChangeMovementSpeed(speedMultiplier);
          bool ownerTeamChanged;
          allCapturePoint.OnAfterTick(agent != null, out ownerTeamChanged);
          if (ownerTeamChanged)
          {
            Team team = agent.Team;
            uint color = team != null ? team.Color : 4284111450U;
            uint color2 = team != null ? team.Color2 : uint.MaxValue;
            allCapturePoint.SetTeamColorsWithAllSynched(color, color2);
            this._capturePointOwners[allCapturePoint.FlagIndex] = team;
            GameNetwork.BeginBroadcastModuleEvent();
            GameNetwork.WriteMessage((GameNetworkMessage) new FlagDominationCapturePointMessage(allCapturePoint.FlagIndex, team != null ? team.TeamIndex : -1));
            GameNetwork.EndBroadcastModuleEvent(GameNetwork.EventBroadcastFlags.None);
            this._gameModeFlagDominationClient?.OnCapturePointOwnerChanged(allCapturePoint, team);
            this.NotificationsComponent.FlagXCapturedByTeamX((SynchedMissionObject) allCapturePoint, agent.Team);
            MPPerkObject.RaiseEventForAllPeers(MPPerkCondition.PerkEventFlags.FlagCapture);
          }
        }
      }
    }

    public int GetNumberOfAttackersAroundFlag(FlagCapturePoint capturePoint)
    {
      Team flagOwnerTeam = this.GetFlagOwnerTeam(capturePoint);
      if (flagOwnerTeam == null)
        return 0;
      int attackersAroundFlag = 0;
      AgentProximityMap.ProximityMapSearchStruct searchStruct = AgentProximityMap.BeginSearch(Mission.Current, capturePoint.Position.AsVec2, 6f);
      while (searchStruct.LastFoundAgent != null)
      {
        Agent lastFoundAgent = searchStruct.LastFoundAgent;
        if (lastFoundAgent.IsHuman && lastFoundAgent.IsActive() && (double) lastFoundAgent.Position.DistanceSquared(capturePoint.Position) <= 36.0 && lastFoundAgent.Team.Side != flagOwnerTeam.Side)
          ++attackersAroundFlag;
        AgentProximityMap.FindNext(Mission.Current, ref searchStruct);
      }
      return attackersAroundFlag;
    }

    public Team GetFlagOwnerTeam(FlagCapturePoint flag)
    {
      return flag == null ? (Team) null : this._capturePointOwners[flag.FlagIndex];
    }

    public override void OnAgentRemoved(
      Agent affectedAgent,
      Agent affectorAgent,
      AgentState agentState,
      KillingBlow blow)
    {
      base.OnAgentRemoved(affectedAgent, affectorAgent, agentState, blow);
      if (this.UseGold() && affectorAgent != null && affectedAgent != null && affectedAgent.IsHuman && blow.DamageType != DamageTypes.Invalid && (agentState == AgentState.Unconscious || agentState == AgentState.Killed))
      {
        bool isFriendly = affectorAgent.Team != null && affectedAgent.Team != null && affectorAgent.Team.Side == affectedAgent.Team.Side;
        Agent.Hitter assistingHitter = affectedAgent.GetAssistingHitter(affectorAgent.MissionPeer);
        MultiplayerClassDivisions.MPHeroClass classForCharacter = MultiplayerClassDivisions.GetMPHeroClassForCharacter(affectedAgent.Character);
        if (affectorAgent.MissionPeer != null && affectorAgent.MissionPeer.Representative is FlagDominationMissionRepresentative representative1)
        {
          int gainsFromKillData = representative1.GetGoldGainsFromKillData(MPPerkObject.GetPerkHandler(affectorAgent.MissionPeer), MPPerkObject.GetPerkHandler(assistingHitter?.HitterPeer), classForCharacter, false, isFriendly);
          if (gainsFromKillData > 0)
            this.ChangeCurrentGoldForPeer(affectorAgent.MissionPeer, representative1.Gold + gainsFromKillData);
        }
        if (assistingHitter?.HitterPeer != null && assistingHitter.HitterPeer.Peer.Communicator.IsConnectionActive && !assistingHitter.IsFriendlyHit && assistingHitter.HitterPeer.Representative is FlagDominationMissionRepresentative representative2)
        {
          int gainsFromKillData = representative2.GetGoldGainsFromKillData(MPPerkObject.GetPerkHandler(affectorAgent.MissionPeer), MPPerkObject.GetPerkHandler(assistingHitter.HitterPeer), classForCharacter, true, isFriendly);
          if (gainsFromKillData > 0)
            this.ChangeCurrentGoldForPeer(assistingHitter.HitterPeer, representative2.Gold + gainsFromKillData);
        }
        if (affectedAgent.MissionPeer?.Team != null && !isFriendly)
        {
          IEnumerable<(MissionPeer, int)> goldRewardsOnDeath = MPPerkObject.GetPerkHandler(affectedAgent.MissionPeer)?.GetTeamGoldRewardsOnDeath();
          if (goldRewardsOnDeath != null)
          {
            foreach ((MissionPeer peer, int baseAmount) in goldRewardsOnDeath)
            {
              if (baseAmount > 0 && peer?.Representative is FlagDominationMissionRepresentative representative3)
              {
                int fromAllyDeathReward = representative3.GetGoldGainsFromAllyDeathReward(baseAmount);
                if (fromAllyDeathReward > 0)
                  this.ChangeCurrentGoldForPeer(peer, representative3.Gold + fromAllyDeathReward);
              }
            }
          }
        }
      }
      if (affectedAgent.IsPlayerControlled)
        affectedAgent.MissionPeer.GetComponent<FlagDominationMissionRepresentative>().UpdateSelectedClassServer((Agent) null);
      else if (MultiplayerOptions.OptionType.NumberOfBotsPerFormation.GetIntValue() > 0 && (this.WarmupComponent == null || !this.WarmupComponent.IsInWarmup) && !affectedAgent.IsMount && affectedAgent.OwningAgentMissionPeer != null && affectedAgent.Formation != null && affectedAgent.Formation.CountOfUnits == 1)
      {
        if (!GameNetwork.IsDedicatedServer)
        {
          MatrixFrame cameraFrame = Mission.Current.GetCameraFrame();
          Vec3 position = cameraFrame.origin + cameraFrame.rotation.u;
          MBSoundEvent.PlaySound(SoundEvent.GetEventIdFromString("event:/alerts/report/squad_wiped"), position);
        }
        GameNetwork.BeginBroadcastModuleEvent();
        GameNetwork.WriteMessage((GameNetworkMessage) new FormationWipedMessage());
        GameNetwork.EndBroadcastModuleEvent(GameNetwork.EventBroadcastFlags.ExcludeOtherTeamPlayers, affectedAgent.OwningAgentMissionPeer.GetNetworkPeer());
      }
      if (this._gameType != MultiplayerGameType.Battle || !affectedAgent.IsHuman || !this.RoundController.IsRoundInProgress || blow.DamageType == DamageTypes.Invalid || agentState != AgentState.Unconscious && agentState != AgentState.Killed)
        return;
      MultiplayerClassDivisions.MPHeroClass classForCharacter1 = MultiplayerClassDivisions.GetMPHeroClassForCharacter(affectedAgent.Character);
      if (affectorAgent?.MissionPeer != null && affectorAgent.Team != affectedAgent.Team)
      {
        FlagDominationMissionRepresentative representative = affectorAgent.MissionPeer.Representative as FlagDominationMissionRepresentative;
        int dataAndUpdateFlags = representative.GetGoldGainFromKillDataAndUpdateFlags(classForCharacter1, false);
        this.ChangeCurrentGoldForPeer(affectorAgent.MissionPeer, representative.Gold + dataAndUpdateFlags);
      }
      Agent.Hitter assistingHitter1 = affectedAgent.GetAssistingHitter(affectorAgent?.MissionPeer);
      if (assistingHitter1?.HitterPeer == null || assistingHitter1.IsFriendlyHit)
        return;
      FlagDominationMissionRepresentative representative4 = assistingHitter1.HitterPeer.Representative as FlagDominationMissionRepresentative;
      int dataAndUpdateFlags1 = representative4.GetGoldGainFromKillDataAndUpdateFlags(classForCharacter1, true);
      this.ChangeCurrentGoldForPeer(assistingHitter1.HitterPeer, representative4.Gold + dataAndUpdateFlags1);
    }

    public override float GetTroopNumberMultiplierForMissingPlayer(MissionPeer spawningPeer)
    {
      if (this._gameType == MultiplayerGameType.Captain)
      {
        List<MissionPeer>[] missionPeerListArray = new List<MissionPeer>[2];
        for (int index = 0; index < missionPeerListArray.Length; ++index)
          missionPeerListArray[index] = new List<MissionPeer>();
        foreach (NetworkCommunicator networkPeer in GameNetwork.NetworkPeers)
        {
          MissionPeer component = networkPeer.GetComponent<MissionPeer>();
          if (component != null && component.Team != null && component.Team.Side != BattleSideEnum.None)
            missionPeerListArray[(int) component.Team.Side].Add(component);
        }
        int[] numArray = new int[2]
        {
          0,
          MultiplayerOptions.OptionType.NumberOfBotsTeam1.GetIntValue()
        };
        numArray[0] = MultiplayerOptions.OptionType.NumberOfBotsTeam2.GetIntValue();
        int f = missionPeerListArray[1].Count + numArray[1] - (missionPeerListArray[0].Count + numArray[0]);
        BattleSideEnum index1 = f == 0 ? BattleSideEnum.None : (f < 0 ? BattleSideEnum.Attacker : BattleSideEnum.Defender);
        if (index1 == spawningPeer.Team.Side)
          return (float) (1.0 + (double) MathF.Abs(f) / (double) (missionPeerListArray[(int) index1].Count + numArray[(int) index1]));
      }
      return 1f;
    }

    protected override void HandleNewClientAfterLoadingFinished(NetworkCommunicator networkPeer)
    {
      if (networkPeer.IsServerPeer)
        return;
      GameNetwork.BeginModuleEventAsServer(networkPeer);
      GameNetwork.WriteMessage((GameNetworkMessage) new FlagDominationMoraleChangeMessage(this.MoraleRounded));
      GameNetwork.EndModuleEventAsServer();
    }
  }
}
